package org.metasketch.simulator.runtime;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.metasketch.logger.Log;
import org.metasketch.simulator.configuration.SimulationPackage;
import org.metasketch.simulator.petri.Transition;
import org.metasketch.simulator.resources.Resource;
import org.metasketch.simulator.resources.ResourceBank;
import org.metasketch.simulator.resources.ResourceBase;
import org.metasketch.simulator.resources.ResourceRequirements;
import org.metasketch.simulator.transformation.PetriNetSimulationPackage;

public class ResourceResolver {

	PetriNetSimulationPackage simulPackage;
	SimulationPackage simulPackage2;
	ResourcePool resourcePool;

	public void initialize() {

		resourcePool = new ResourcePool();
		ResourceBank resources = simulPackage.getResources();
		resourcePool.initialize(resources);

		initCompanyStaff();
		initPresentialResourcesAndDurations();
		initChannelsTransactionResourcesAndDurations();
		initChannelDistributions();

	}

	public boolean areRequirementsSatisfiable(Transition transition,
			Process process) {

	}

	public void assignResources(Transition transition, Process process) {

	}

	private boolean isRequirementSatisfiable(ResourceBase resource, Long amount)
			throws Exception {

		if (process.getOwnedResources().canRequest(resource, amount))
			return true;

		if (resourceManager.getResourcePool().canRequest(resource, amount))
			return true;

		return false;
	}

	private Map<Resource, Long> assignRequirements(ResourceRequirements reqs)
			throws Exception {

		ResourcePool assignedPool = new ResourcePool();
		Map<Resource, Long> assigned = new HashMap<Resource, Long>();

		Map<ResourceBase, Long> map = reqs.getRequirements();
		Set<Entry<ResourceBase, Long>> entries = map.entrySet();
		for (Entry<ResourceBase, Long> entry : entries) {
			ResourceBase resource = entry.getKey();
			Long amount = entry.getValue();

			if (process.getOwnedResources().canRequest(resource, amount)) {
				Map<Resource, Long> requested = process.getOwnedResources()
						.request(resource, amount);
				// addRequested(assigned, requested);
				process.getOwnedActiveResources().releaseResources(requested);

				assignedPool.releaseResources(requested);

			} else if (resourceManager.getResourcePool().canRequest(resource,
					amount)) {
				Map<Resource, Long> requested = resourceManager
						.getResourcePool().request(resource, amount);
				// addRequested(assigned, requested);
				process.getAssignedActiveResources()
						.releaseResources(requested);

				assignedPool.releaseResources(requested);

			}

		}

		Set<Entry<ResourceBase, Long>> wazza = assignedPool.getResources()
				.entrySet();
		for (Entry<ResourceBase, Long> entry : wazza) {
			Log.println("Assigned resource " + entry.getKey().getName() + " - "
					+ entry.getValue());
		}

		return assigned;

	}

	private boolean areRequirementsSatisfiable(ResourceRequirements reqs)
			throws Exception {

		Map<ResourceBase, Long> map = reqs.getRequirements();
		Set<Entry<ResourceBase, Long>> entries = map.entrySet();
		for (Entry<ResourceBase, Long> entry : entries) {
			ResourceBase resource = entry.getKey();
			Long amount = entry.getValue();

			if (!isRequirementSatisfiable(resource, amount))
				return false;

		}

		return true;
	}

	protected void releaseResources() throws Exception {
		// release the resources...
		// owned resources
		process.getOwnedResources().release(
				process.getOwnedActiveResources().getResources());

		Set<Entry<ResourceBase, Long>> entries = process
				.getOwnedActiveResources().getResources().entrySet();
		for (Entry<ResourceBase, Long> entry : entries) {
			Log.println("Releasing resource " + entry.getKey().getName()
					+ " - " + entry.getValue());
		}

		process.getOwnedActiveResources().getResources().clear();
		// assigned external resources
		resourceManager.getResourcePool().release(
				process.getAssignedActiveResources().getResources());

		entries = process.getAssignedActiveResources().getResources()
				.entrySet();
		for (Entry<ResourceBase, Long> entry : entries) {
			Log.println("Releasing resource " + entry.getKey().getName()
					+ " - " + entry.getValue());
		}

		process.getAssignedActiveResources().getResources().clear();
	}

	// public void setResourceManager(ResourceManager resourceManager) {
	// this.resourceManager = resourceManager;
	//
	// }

	public PetriNetSimulationPackage getSimulPackage() {
		return simulPackage;
	}

	public void setSimulPackage(PetriNetSimulationPackage simulPackage) {
		this.simulPackage = simulPackage;
	}

	public SimulationPackage getSimulPackage2() {
		return simulPackage2;
	}

	public void setSimulPackage2(SimulationPackage simulPackage2) {
		this.simulPackage2 = simulPackage2;
	}

	// public ResourceManager getResourceManager() {
	// return resourceManager;
	// }

}
